#include "WS2812.h"

uint16_t send_Buf[NUM];
//extern TIM_HandleTypeDef htim3;
extern SPI_HandleTypeDef hspi1;


uint8_t RGB_BIT_Buffer[RGB_BIT];
uint8_t buffer[RGB_BIT*LED_NUMS];
LEDType LED[LED_NUMS];


void WS2812SendData(uint8_t *sendBuff, uint16_t sendSize)
{
    HAL_SPI_Transmit_DMA(&hspi1, sendBuff, sendSize);

}
void WS2812_Update()
{
    HAL_SPI_Transmit_DMA(&hspi1,buffer,RGB_BIT*LED_NUMS);
}
/**
create 24 byte sent by SPI using RGB values.
*/
static  void WS2812_CreatData(uint8_t R,uint8_t G,uint8_t B)
{
    uint8_t temp[RGB_BIT] = {0};
    for (uint8_t i=0; i<8; i++) {
        temp[7-i] =  (G & 0x01) ? WS2812_1 : WS2812_0;
        G = G >> 1;
    }
    for (uint8_t i=0; i<8; i++) {
        temp[15-i] =  (R & 0x01) ? WS2812_1 : WS2812_0;
        R = R >> 1;
    }
    for (uint8_t i=0; i<8; i++) {
        temp[23-i] =  (B & 0x01) ? WS2812_1 : WS2812_0;
        B = B >> 1;
    }
    memcpy(RGB_BIT_Buffer, temp, RGB_BIT);
}
/**
cook the whole buffer made by many(16 pieces) RGB_BIT_Buffers.
*/
void WS2812_MakeBuffer()
{
    for(uint16_t i=0; i < LED_NUMS; i++)
    {
        WS2812_CreatData(LED[i].R,LED[i].G,LED[i].B);
        memcpy(buffer + i * RGB_BIT, RGB_BIT_Buffer, RGB_BIT);
    }
}

void WS2812_TurnOff()
{
    for(uint16_t i=0; i<LED_NUMS*24; i++)
    {
        buffer[i]=WS2812_0;
    }
}

/**
an led of position will bright with color value
pos is [0 , max-1]
*/
static void WS2812_Color_Pos(uint32_t color,uint16_t Pos)
{
    uint8_t R,G,B;
    uint16_t i;

    R=(color >> 16 ) & 0x00FF;
    G=(color >> 8  ) & 0x0000FF;
    B=(color 	   ) & 0x0000FF;

    WS2812_CreatData(R,G,B);
    if(Pos < LED_NUMS && Pos >=0)
    {
        memcpy(buffer + RGB_BIT * Pos, RGB_BIT_Buffer,RGB_BIT);
    }
    else
    {
        WS2812_TurnOff();
    }
}

static uint8_t wheel_index = 0;
void WS2812_ShowRainbowCycle(void)
{
    for (uint16_t i = 0; i < LED_NUMS; i++) {
        uint32_t color = Wheel((i * 256 / LED_NUMS + wheel_index) & 0xFF);
        WS2812_Color_Pos(color, i);
    }
    WS2812_Update();
    wheel_index++;
}





//上面是SPI+DMA控制
//下面是PWM+DMA控制
void WS_Load(void)
{
    //HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_2, (uint32_t *)send_Buf, NUM);
}

// 关闭所有LED灯
void WS_CloseAll(void)
{
    uint16_t i;

    for (i = 0; i < PIXEL_NUM * 24; i++)
        send_Buf[i] = WS0; // 写入逻辑0的占空比

    for (i = PIXEL_NUM * 24; i < NUM; i++)
        send_Buf[i] = 0; // 占空比比为0，全为低电平

    WS_Load();
}

/**
 * @brief 全部led灯设置成一样的亮度，其中RGB分别设置亮度
 * WS2812的写入顺序是GRB，高位在前面
*/
void WS_WriteAll_RGB(uint8_t n_R, uint8_t n_G, uint8_t n_B)
{
    uint16_t i, j;
    uint8_t dat[24];

    // 将RGB数据进行转换
    for (i = 0; i < 8; i++)
    {
        dat[i] = ((n_G & 0x80) ? WS1 : WS0);
        n_G <<= 1;
    }
    for (i = 0; i < 8; i++)
    {
        dat[i + 8] = ((n_R & 0x80) ? WS1 : WS0);
        n_R <<= 1;
    }
    for (i = 0; i < 8; i++)
    {
        dat[i + 16] = ((n_B & 0x80) ? WS1 : WS0);
        n_B <<= 1;
    }

    for (i = 0; i < PIXEL_NUM; i++)
    {
        for (j = 0; j < 24; j++)
        {
            send_Buf[i * 24 + j] = dat[j];
        }
    }

    for (i = PIXEL_NUM * 24; i < NUM; i++)
    {
        send_Buf[i] = 0; // 占空比比为0，全为低电平
    }

    WS_Load();
}

uint32_t WS281x_Color(uint8_t red, uint8_t green, uint8_t blue)
{
    return green << 16 | red << 8 | blue;
}

/**
  * @brief  Set the color of No.n light in 24bit-format .
  * @note   None
  * @param  n: No.n lamp light, ranges from 0 to (PIXEL_NUM-1)
  * @param  GRBColor: color value of No.n light in 24bit-format(8 bit G + 8 bit R +8 bit B)
  * @retval None
  */
void WS281x_SetPixelColor(uint16_t n, uint32_t GRBColor)
{
    uint8_t i;
    if (n < PIXEL_NUM)
    {
        for (i = 0; i < 24; ++i)
        {
            send_Buf[24 * n + i] = (((GRBColor << i) & 0X800000) ? WS1 : WS0);
        }
    }
}

/**
  * @brief  Set the color of No.n light in RGB-format .
  * @note   None
  * @param  n: No.n lamp light, ranges from 0 to (PIXEL_NUM-1)
  * @param  red: red color value of No.n light in RGB-format
  * @param  green: greeen color value of No.n light in RGB-format
  * @param  blue: blue color value of No.n light in RGB-format
  * @retval None
  */
void WS281x_SetPixelRGB(uint16_t n, uint8_t red, uint8_t green, uint8_t blue)
{
    uint8_t i;

    if (n < PIXEL_NUM)
    {
        for (i = 0; i < 24; ++i)
        {
            send_Buf[24 * n + i] = (((WS281x_Color(red, green, blue) << i) & 0X800000) ? WS1 : WS0);
        }
    }
}

static uint32_t Wheel(uint8_t WheelPos)
{
    WheelPos = 255 - WheelPos;
    if (WheelPos < 85)
    {
        return WS281x_Color(255 - WheelPos * 3, 0, WheelPos * 3);
    }
    if (WheelPos < 170)
    {
        WheelPos -= 85;
        return WS281x_Color(0, WheelPos * 3, 255 - WheelPos * 3);
    }
    WheelPos -= 170;
    return WS281x_Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

void rainbow(uint8_t wait)
{
    uint32_t timestamp = HAL_GetTick();
    uint16_t i;
    static uint8_t j;
    static uint32_t next_time = 0;

    uint32_t flag = 0;
    if (next_time < wait)
    {
        if ((uint64_t)timestamp + wait - next_time > 0)
            flag = 1;
    }
    else if (timestamp > next_time)
    {
        flag = 1;
    }
    if (flag) // && (timestamp - next_time < wait*5))
    {
        j++;
        next_time = timestamp + wait;
        for (i = 0; i < PIXEL_NUM; i++)
        {
            WS281x_SetPixelColor(i, Wheel((i + j) & 255));
        }
    }
    WS_Load();
}

void rainbowCycle(uint8_t wait)
{
    uint32_t timestamp = HAL_GetTick();
    uint16_t i;
    static uint8_t j;
    static uint32_t next_time = 0;

    static uint8_t loop = 0;
    if (loop == 0)
        next_time = timestamp;
    loop = 1; //首次调用初始化

    if ((timestamp > next_time)) // && (timestamp - next_time < wait*5))
    {
        j++;
        next_time = timestamp + wait;
        for (i = 0; i < PIXEL_NUM; i++)
        {
            WS281x_SetPixelColor(i, Wheel(((i * 256 / (PIXEL_NUM)) + j) & 255));
        }
    }
    WS_Load();
}



//显存数组，长度为 灯的数量*24+复位周期
uint16_t WS2812_RGB_Buff[LED_NUM*DATA_LEN+WS2812_RST_NUM] = {0};

/**
 * 函数：WS2812单灯设置函数
 * 参数：num:灯的位置，R、G、B分别为三个颜色通道的亮度，最大值为255
 * 作用：单独设置每一个WS2812的颜色
***/
void WS2812_Set(uint16_t num,uint8_t R,uint8_t G,uint8_t B)
{
    uint32_t indexx=(num*(3*8));
    for (uint8_t i = 0; i < 8; i++)
    {
        //填充数组
        WS2812_RGB_Buff[indexx+i]      = (G << i) & (0x80)?WS_H:WS_L;
        WS2812_RGB_Buff[indexx+i + 8]  = (R << i) & (0x80)?WS_H:WS_L;
        WS2812_RGB_Buff[indexx+i + 16] = (B << i) & (0x80)?WS_H:WS_L;
    }
    WS2812_Init();
}

//WS2812初始化函数
void WS2812_Init()
{
    //设置关闭所有灯
    for(int i=0; i<8; i++)
    {
        WS2812_Set(i,0,20,0);
    }
    //作用：调用DMA将显存中的内容实时搬运至定时器的比较寄存器
// HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_2,(uint32_t *)WS2812_RGB_Buff,sizeof(WS2812_RGB_Buff)/sizeof(uint16_t));
}


static uint16_t wi=0;

void WS2812_Show_Wheel()
{
    wi++;
    WS2812_Color_Pos(0xFF0000,(wi)%16);
//    WS2812_Color_Pos(0XFF7F00,(wi+1)%16);
//    WS2812_Color_Pos(0XFFFF00,(wi+2)%16);
//    WS2812_Color_Pos(0X7FFF00,(wi+3)%16);
//    WS2812_Color_Pos(0X00FF00,(wi+4)%16);
//    WS2812_Color_Pos(0X00FF7F,(wi+5)%16);
//    WS2812_Color_Pos(0X00FFFF,(wi+6)%16);
//    WS2812_Color_Pos(0X007FFF,(wi+7)%16);
//    WS2812_Color_Pos(0X0000FF,(wi+8)%16);
//    WS2812_Color_Pos(0X7F00FF,(wi+9)%16);
//    WS2812_Color_Pos(0XFF00FF,(wi+10)%16);
//    WS2812_Color_Pos(0XFF007F,(wi+11)%16);
//    WS2812_Color_Pos(0XFF0000,(wi+12)%16);
//    WS2812_Color_Pos(0XFF7F00,(wi+13)%16);
//    WS2812_Color_Pos(0XFFFF00,(wi+14)%16);
//    WS2812_Color_Pos(0X7FFF00,(wi+15)%16);
    WS2812_Update();
}





static uint32_t last_update = 0;
#define COLOR_INTERVAL 5    // 每次颜色变化的间隔时间（ms）
#define STEP 1               // 每次移动的步长

void WS2812_ShowGradient(void)
{
    uint32_t current_tick = HAL_GetTick();

    if ((current_tick - last_update) >= COLOR_INTERVAL)
    {
        static uint8_t hue = 0;  // HSV 色调值，0~255 表示一圈颜色

        for (uint16_t i = 0; i < LED_NUMS; i++)
        {
            uint8_t h = (hue + (i * 255 / LED_NUMS)) % 255;
            uint32_t color = Wheel(h);  // Wheel 函数已在你的代码中定义
            WS2812_Color_Pos(color, i);
        }

        WS2812_Update();  // 触发 SPI DMA 更新

        hue += STEP;
        if (hue >= 255)
            hue = 0;

        last_update = current_tick;
    }
}





